package com.tuoyu.peopletest.view.ac;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.stresscube.usbdevice.USBDevicePDHIDWithAddress;
import com.stresscube.usbdevice.data.ParaName;
import com.stresscube.usbdevice.data.ParaScan;
import com.tuoyu.peopletest.R;
import com.tuoyu.peopletest.utils.SettingsClass;
import com.tuoyu.peopletest.utils.Utils;

import java.util.ArrayList;
import java.util.List;

public class MainActivityTest extends AppCompatActivity {
    USBDevicePDHIDWithAddress mDevice = new USBDevicePDHIDWithAddress();
    TextView mtvResult;
    ArrayList<Integer> mListResult = new ArrayList<Integer>();
    LineChart mLineChart;   //显示曲线
    boolean mbTestStop = false;

    byte position = (byte) 0x03, adPosition = (byte) 0x01;
    int start = 60, stop = 170, home = 0, step = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_test);
        mtvResult = findViewById(R.id.tvResult);
        mLineChart = findViewById(R.id.lineChart_01);

        initData();
    }

    @Override
    protected void onStart() {
        mDevice.init(this);
        super.onStart();
    }

    @Override
    protected void onStop() {
        mDevice.release();
        super.onStop();
    }

    private void initData() {
        SettingsClass.getSettings();
        ((EditText) findViewById(R.id.etFrequency)).setText(SettingsClass.getMainTestFrequency() + "");
        ((EditText) findViewById(R.id.etGain)).setText(SettingsClass.getMainTesADGain() + "");
        switch (SettingsClass.getMainTestLED()) {
            case 0:
                ((RadioGroup) findViewById(R.id.rgLED)).check(R.id.rbLED365);
                break;
            case 1:
                ((RadioGroup) findViewById(R.id.rgLED)).check(R.id.rbLED470);
                break;
            case 2:
                ((RadioGroup) findViewById(R.id.rgLED)).check(R.id.rbLED525);
                break;
        }
        ((RadioGroup) findViewById(R.id.rgADPosition)).setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if (checkedId == R.id.rbADPosition1)
                    adPosition = 0x01;
                else if (checkedId == R.id.rbADPosition2)
                    adPosition = 0x02;
            }
        });
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnRead:
                read();
                break;
            case R.id.btnScanRead:
                scanRead();
                break;
            case R.id.btnStop:
                mbTestStop = true;
                break;
            case R.id.btnMain:
                Intent mainIntent = new Intent(this, MainActivity.class);
                startActivity(mainIntent);
                break;
            case R.id.btnLEDOn:
                ledOn();
                break;
            case R.id.btnLEDOff:
                ledOff();
                break;
            case R.id.btnSetFrequencyGain:
                setFrequencyAndGain();
                break;
            case R.id.btnGetFrequencyGain:
                getFrequencyAndGain();
                break;
            case R.id.btnReadDevice:
                readFromDevice();
                break;
            case R.id.btnWriteDevice:
                writeToDevice();
                break;
            case R.id.btnWriteDeviceName:
                writeNameToDevice();
                break;
            case R.id.btnReadDeviceName:
                readNameFromDevice();
                break;
            case R.id.btnWriteZeroOffset:
                writeZeroOffsetToDevice();
                break;
            case R.id.btnReadZeroOffset:
                readZeroOffsetFromDevice();
                break;
        }
    }

    private void readFromDevice() {
        ParaScan para = mDevice.readParaScanFromDevice();
        if (para == null) {
            displayText("从设备读校准数据失败");
            return;
        }

        ((EditText) findViewById(R.id.edtStart)).setText(String.valueOf(para.paraScanFluorescence.start & 0xFF));
        ((EditText) findViewById(R.id.edtStop)).setText(String.valueOf(para.paraScanFluorescence.stop & 0xFF));
        ((EditText) findViewById(R.id.edtBrightness)).setText(String.valueOf(para.paraScanFluorescence.getBrightness()));
        ((EditText) findViewById(R.id.edtColor)).setText(Utils.byte2hexString(para.paraScanFluorescence.color));
        displayText("从设备读校准数据成功");
    }

    private void writeToDevice() {
        ParaScan para = new ParaScan();
        para.paraScanFluorescence.start = (byte) Integer.parseInt(((EditText) findViewById(R.id.edtStart)).getText().toString());
        para.paraScanFluorescence.stop = (byte) Integer.parseInt(((EditText) findViewById(R.id.edtStop)).getText().toString());
        para.paraScanFluorescence.setBrightness(Integer.parseInt(((EditText) findViewById(R.id.edtBrightness)).getText().toString()));
        para.paraScanFluorescence.color = Utils.hexString2byte(((EditText) findViewById(R.id.edtColor)).getText().toString());

        if (mDevice.saveParaScan2Device(para))
            displayText("写数据到设备成功");
        else
            displayText("写数据到设备失败！！");
    }

    private void readNameFromDevice() {
        ParaName para = mDevice.readParaNameFromDevice();
        if (para == null) {
            displayText("读设备出错");
            return;
        }

        ((EditText) findViewById(R.id.edtDeviceName)).setText(para.name);
        ((EditText) findViewById(R.id.edtDeviceNo)).setText(para.serialNo);

        displayText("读设备成功，设备名：" + para.name + " 序列号：" + para.serialNo);
    }

    private void writeNameToDevice() {
        ParaName para = new ParaName();

        String strName = ((EditText) findViewById(R.id.edtDeviceName)).getText().toString();
        String strNo = ((EditText) findViewById(R.id.edtDeviceNo)).getText().toString();
        para.name = strName;
        para.serialNo = strNo;

        if (mDevice.saveParaName2Device(para))
            displayText("写数据到设备成功");
        else
            displayText("写数据到设备失败！！");
    }

    void displayText(String strMsg) {
        String msg = mtvResult.getText().toString();
        msg = strMsg + "\r\n" + msg;
        mtvResult.setText(msg);
    }

    void read() {
        new Test().start();
    }

    void scanRead() {
        new ScanTest().start();
    }

    void ledOn() {
        int checkedId = ((RadioGroup) findViewById(R.id.rgLED)).getCheckedRadioButtonId();
        int brightness = 280;
        if (((RadioGroup) findViewById(R.id.rgBrightness)).getCheckedRadioButtonId() == R.id.rb560)
            brightness = 560;
        if (checkedId == R.id.rbLED365)
            ledOn365(brightness);
        else if (checkedId == R.id.rbLED470)
            ledOn470(brightness);
        else if (checkedId == R.id.rbLED525)
            ledOn525(brightness);

        if (checkedId == R.id.rbLED365)
            SettingsClass.setMainTestLED(0);
        else if (checkedId == R.id.rbLED470)
            SettingsClass.setMainTestLED(1);
        else SettingsClass.setMainTestLED(2);
        SettingsClass.saveSettings();
    }

    void ledOn525(int brightness) {
        if (mDevice.LEDOn(position, (byte) 0x40, brightness))
            displayText("开灯525成功");
        else
            displayText("开灯525失败");
    }

    void ledOn470(int brightness) {
        if (mDevice.LEDOn(position, (byte) 0x2a, brightness))
            displayText("开灯470成功");
        else
            displayText("开灯470失败");
    }

    void ledOn365(int brightness) {
        if (mDevice.LEDOn(position, (byte) 0x15, brightness))
            displayText("开灯365成功");
        else
            displayText("开灯365失败");
    }

    private void ledOff() {
        if (mDevice.LEDOff(position))
            displayText("关灯成功");
        else
            displayText("关灯失败");
    }

    void setFrequencyAndGain() {
        int frequency, gain;
        frequency = Integer.parseInt(((EditText) findViewById(R.id.etFrequency)).getText().toString());
        if (frequency < 10) {
            frequency = 10;
            ((EditText) findViewById(R.id.etFrequency)).setText(frequency + "");
        }
        gain = Integer.parseInt(((EditText) findViewById(R.id.etGain)).getText().toString());
        if (gain <= 0) {
            gain = 0;
            ((EditText) findViewById(R.id.etGain)).setText(gain + "");
        }
        if (mDevice.SetADCFrequencyAndGain(adPosition, frequency, gain))
            displayText("设置频率" + frequency + "，增益为" + gain);
        else
            displayText("设置频率增益失败");

        SettingsClass.setMainTestFrequency(frequency);
        SettingsClass.setMainTestADGain(gain);
        SettingsClass.saveSettings();
    }

    void getFrequencyAndGain() {
        int[] frequencyAndGain = new int[2];
        if (mDevice.GetADCFrequencyAndGain(adPosition, frequencyAndGain)) {
            displayText("频率 " + frequencyAndGain[0] + "，增益 " + frequencyAndGain[1]);
            showFrequency(frequencyAndGain[0]);
            showGain(frequencyAndGain[1]);
        } else
            displayText("获取频率增益失败");
    }

    void writeZeroOffsetToDevice() {
        int offset;
        offset = Integer.parseInt(((EditText) findViewById(R.id.etZeroOffset)).getText().toString());
        if (offset < 0) {
            offset = 0;
            ((EditText) findViewById(R.id.etZeroOffset)).setText(offset + "");
        } else if (offset > 100) {
            offset = 100;
            ((EditText) findViewById(R.id.etZeroOffset)).setText(offset + "");
        }
        if (mDevice.SetZeroOffset(offset))
            displayText("设置零点补偿 " + offset);
        else
            displayText("设置零点补偿失败");
    }

    void readZeroOffsetFromDevice() {
        int offset = mDevice.GetZeroOffset();
        if (offset >= 0) {
            displayText("零点补偿 " + offset);
            ((EditText) findViewById(R.id.etZeroOffset)).setText("" + offset);
        } else
            displayText("获取零点补偿失败");
    }

    private void showGain(int adGain) {
        ((EditText) findViewById(R.id.etGain)).setText("" + adGain);
    }

    private void showFrequency(int frequency) {
        ((EditText) findViewById(R.id.etFrequency)).setText("" + frequency);
    }

    class ScanTest extends Thread {
        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            if (!mDevice.StopADReceive())
                Log.e("", "StopAD error");
            if (!mDevice.GoHome())
                Log.e("", "GoHome error");
            if (!mDevice.MoveTray(start))
                Log.e("", "MoveTray start error");
            if (!mDevice.StartMoveTray(stop))
                Log.e("", "StartMoveTray stop error");

            if (!mDevice.StartADReceive(adPosition)) {
                sendDisplayMessage("发送开始采集命令出错");
                mDevice.StopADReceive();
                mDevice.MoveTray(home);
                return;
            }
            sendDisplayMessage("开始采集");

            mDevice.GetADAfterStart();
            mDevice.GetADAfterStart();
            mDevice.GetADAfterStart();

            mListResult.clear();
            mbTestStop = false;
            int nData = 0;
            while (!mbTestStop) { //连续读
                int ad = mDevice.GetADAfterStart();
                if (ad < 0) {
                    break;
                }
                if (ad == 0)
                    break;
                mListResult.add(ad);
//                if (mListResult.size() > 0 && mListResult.size() % 50 == 0)
                SendDrawChart();
                nData++;
                if (nData > (stop - start) * step + 100) {
                    sendDisplayMessage("没有接收到停止命令，强制停止");
                    break;
                }
            }

            mDevice.StopADReceive();
            mDevice.MoveTray(home);

            showResult();
            sendDisplayMessage("停止采集");
        }
    }

    class Test extends Thread {
        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            mDevice.StopADReceive();

            if (!mDevice.StartADReceive(adPosition)) {
                sendDisplayMessage("发送开始采集命令出错");
                mDevice.StopADReceive();
                return;
            }
            sendDisplayMessage("开始采集");

            mDevice.GetADAfterStart();
            mDevice.GetADAfterStart();
            mDevice.GetADAfterStart();

            mListResult.clear();
            mbTestStop = false;
            for (int i = 0; i < 1000; i++) {
                if (mbTestStop)
                    break;
                int ad = mDevice.GetADAfterStart();
                if (ad > 0) {
                    mListResult.add(ad);
                    if (mListResult.size() > 0 && mListResult.size() % 50 == 0)
                        SendDrawChart();
                } else {
                    sendDisplayMessage("接收数据格式错误");
                }
            }

            mDevice.StopADReceive();

            showResult();
            sendDisplayMessage("停止采集");
        }
    }

    private void showResult() {
        if (mListResult.size() == 0)
            return;
        double total = 0;
        for (int i = 0; i < mListResult.size(); i++)
            total += mListResult.get(i);
        int mean = (int) (total / mListResult.size() + 0.5);
        double stdev = stdev(mListResult, mean);
        double cv = ((int) ((stdev / mean * 100) * 100)) / 100.0;
        sendDisplayMessage("平均值: " + mean + " stdev: " + (int) (stdev + 0.5) + " CV: " + cv + "%");
    }

    double stdev(ArrayList<Integer> data, int average) {
        if (data == null || data.size() <= 1)
            return -1;
        double sum = 0;
        for (int i = 0; i < data.size(); i++) {
            sum += Math.pow(data.get(i) - average, 2);
        }
        return Math.sqrt(sum / (data.size() - 1));
    }

    void SendDrawChart() {
        mHandler.sendEmptyMessage(3);
    }

    private void DrawLineChart() {
        if (mListResult == null || mListResult.size() <= 0) {
            Toast.makeText(this, "没有数据", Toast.LENGTH_LONG).show();
            return;
        }

        List<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
        List<Entry> entries = new ArrayList<Entry>();
        for (int i = 0; i < mListResult.size(); i++)
            entries.add(new Entry(i, mListResult.get(i)));
        LineDataSet dataSet = new LineDataSet(entries, "ad");
        int color = Color.BLUE;
        dataSet.setColor(color);
        dataSet.setValueTextColor(color);
        dataSet.setCircleColor(color);
        dataSet.setCircleHoleColor(color);
        dataSets.add(dataSet);

        LineData data = new LineData(dataSets);
        mLineChart.setData(data);
        mLineChart.invalidate(); // refresh
    }

    Handler mHandler = new Handler(msg -> {
        switch (msg.what) {
            case 1:
            case 5:
            case 6:
                displayText((String) msg.obj);
                break;
            case 2:
//                    DisplayData((int[]) msg.obj);
                break;
            case 3:
                DrawLineChart();
                break;
            case 4:
                displayText("AD: " + (int) msg.obj);
                break;
        }
        return true;
    });

    void sendDisplayMessage(String str) {
        Message message = new Message();
        message.what = 1;
        message.obj = str;
        mHandler.sendMessage(message);
    }

}